package com.raycloud.controller;

import com.alibaba.fastjson.JSON;
import com.google.common.base.Charsets;
import com.google.common.io.Files;
import com.raycloud.constants.SystemConstant;
import com.raycloud.dao.EndProjectDAO;
import com.raycloud.dao.FrontProjectDAO;
import com.raycloud.dao.VersionDAO;
import com.raycloud.pojo.EndProject;
import com.raycloud.pojo.EndProjectInfo;
import com.raycloud.pojo.FrontProject;
import com.raycloud.pojo.Version;
import com.raycloud.query.FrontProjectQuery;
import com.raycloud.query.VersionQuery;
import com.raycloud.util.CmdUtil;
import com.raycloud.util.RedisAPI;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by donar on 17/4/19.
 */
@Controller
@RequestMapping("/version")
public class VersionController {
    @Autowired
    FrontProjectDAO frontProjectDAO;
    @Autowired
    EndProjectDAO endProjectDAO;
    @Autowired
    VersionDAO versionDAO;
    @Autowired
    RedisAPI redisAPI;
    @RequestMapping(value = "add")
    @ResponseBody
    public Response addVersion(String versionName,String frontProjectInfo,String endProjectInfo){

        if(StringUtils.isEmpty(versionName)) return Response.error("版本号不能为空");
        if(StringUtils.isEmpty(frontProjectInfo)) return Response.error("前端项目不能为空");
        if(StringUtils.isEmpty(endProjectInfo)) return Response.error("后端配置不能为空");
        List<EndProjectInfo> endProjectList=JSON.parseArray(endProjectInfo, EndProjectInfo.class);
        List<EndProjectInfo> realList = new ArrayList<EndProjectInfo>();
        for (EndProjectInfo info:endProjectList){
            if (StringUtils.isEmpty(info.getLocation())||(StringUtils.isEmpty(info.getProject())&&StringUtils.isEmpty(info.getProxyPath()))) continue;realList.add(info);
        }
        if(realList.size()==0) return Response.error("请输入正确的后端配置");
        if(versionDAO.getVersionByKey(versionName)!=null) return Response.error("当前版本号已存在");
        for (EndProjectInfo info : realList){
            if(StringUtils.isEmpty(info.getProxyPath())){
                EndProject endproject = endProjectDAO.getEndProjectByKey(info.getProject());
                info.setProxyPath("http://127.0.0.1:"+endproject.getTomcatPort());
            }
        }
        Version version = new Version();
        version.setVersionId(versionName);
        version.setFrontProjectsInfo(frontProjectInfo);
        version.setEndProjectsInfo(JSON.toJSONString(realList));
        versionDAO.addVersion(version);
       return Response.success("添加成功");
    }


    @RequestMapping(value = "edit")
    @ResponseBody
    public Response editVersion(String versionName,String frontProjectInfo,String endProjectInfo){
        if(StringUtils.isEmpty(versionName)) return Response.error("版本号不能为空");
        if(StringUtils.isEmpty(frontProjectInfo)) return Response.error("前端项目不能为空");
        if(StringUtils.isEmpty(endProjectInfo)) return Response.error("后端配置不能为空");
        List<EndProjectInfo> endProjectList=JSON.parseArray(endProjectInfo, EndProjectInfo.class);
        List<EndProjectInfo> realList = new ArrayList<EndProjectInfo>();
        for (EndProjectInfo info:endProjectList){
            if (StringUtils.isEmpty(info.getLocation())||(StringUtils.isEmpty(info.getProject())&&StringUtils.isEmpty(info.getProxyPath()))) continue;realList.add(info);
        }
        if(realList.size()==0) return Response.error("请输入正确的后端配置");
        Version version = versionDAO.getVersionByKey(versionName);
        if(version==null) return Response.error("版本号不存在");
        for (EndProjectInfo info : realList){
            if(StringUtils.isEmpty(info.getProxyPath())){
                EndProject endproject = endProjectDAO.getEndProjectByKey(info.getProject());
                info.setProxyPath("http://127.0.0.1:"+endproject.getTomcatPort());
            }
        }
        version.setVersionId(versionName);
        version.setFrontProjectsInfo(frontProjectInfo);
        version.setEndProjectsInfo(JSON.toJSONString(realList));
        versionDAO.updateVersionByKey(version);
        return Response.success("添加成功");
    }
    @RequestMapping(value = "list")
    @ResponseBody
    public Response list(){
        List<Version> list = versionDAO.getVersionList(new VersionQuery());
        return Response.success(list);
    }
    @RequestMapping(value = "delete")
    @ResponseBody
    public Response delete(String versionName){
        versionDAO.deleteByKey(versionName);
        return Response.success("删除成功");
    }
    @RequestMapping(value = "reload")
    @ResponseBody
    public Response reload(String versionName) throws IOException {
        List<Version> versions = versionDAO.getVersionList(new VersionQuery());
        String content = buildNginxConfig(versions);
        System.out.println(content);
        File file = new File("/usr/local/openresty/nginx/conf/nginx.conf");
        Files.write(content,file, Charsets.UTF_8);
        String result =CmdUtil.exec("/usr/local/openresty/bin/openresty -s reload");
        return Response.success(result);
    }
    @RequestMapping(value = "setVersionOld")
    @ResponseBody
    public Response setVersion(String versionName, HttpServletResponse response) throws IOException {
        Cookie versionCookie = new Cookie("abversion",versionName);
        versionCookie.setDomain(".superseller.cn");
        versionCookie.setPath("/");
        response.addCookie(versionCookie);
        return Response.success("切换版本成功  当前版本为 " +versionName);
    }

    @RequestMapping(value = "setVersion")
    @ResponseBody
    public Response setRVersion(String versionName,HttpServletRequest request) throws IOException {
        String ip= getIpAddr(request);
        redisAPI.set(ip,versionName);
        return Response.success("切换版本成功  当前版本为 " +versionName);
    }

    @RequestMapping(value = "current")
    @ResponseBody
    public Response getRVersion(HttpServletRequest request) throws IOException {
        String ip= getIpAddr(request);
        String version = redisAPI.get(ip);
        return Response.success(version);
    }


    @RequestMapping(value = "current2")
    @ResponseBody
    public Response current(HttpServletRequest request){
        String ip = getIpAddr(request);
        Cookie[] cookies = request.getCookies();
        for (Cookie cookie:cookies){
            if(cookie.getName().equals("abversion"))return Response.success(cookie.getValue() + " 当前IP:" + ip);
        }
        return Response.success("unknown"+ " 当前IP:" + ip);
    }

    public String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    private String buildNginxConfig(List<Version> versions) {
        StringBuffer sb  = new StringBuffer("");
        sb.append("worker_processes  1;\n" +
                "events {\n" +
                "    worker_connections  1024;\n" +
                "}\n" +
                "\n" +
                "\n" +
                "http {\n" +
                "    include       mime.types;\n" +
                "    init_by_lua_file /root/init.lua;\n"+
                "    default_type  application/octet-stream;\n" +
                "    sendfile        on;\n" +
                "    keepalive_timeout  65;\n" +
                "    server {\n" +
                "            listen       80;\n" +
                "            server_name  publish.superseller.cn;\n" +
                "            charset utf-8;\n" +
                "            index /index.html; \n" +
                "            location / {\n" +
                "                    proxy_pass http://127.0.0.1:6666;\n" +
                "                    proxy_redirect              off;\n" +
                "                    proxy_set_header            Host $host;\n" +
                "                    proxy_set_header            X-Real-IP $remote_addr;\n" +
                "                    proxy_set_header            X-Forwarded-For $proxy_add_x_forwarded_for;\n" +
                "                    client_max_body_size 10m;\n" +
                "                    client_body_buffer_size 128k;\n" +
                "                    proxy_connect_timeout 90;\n" +
                "                    proxy_send_timeout 120;\n" +
                "                    proxy_read_timeout 120;\n" +
                "                    proxy_buffer_size 4k;\n" +
                "                    proxy_buffers 4 32k;\n" +
                "                    proxy_busy_buffers_size 64k;\n" +
                "                    proxy_temp_file_write_size 64k;\n" +
                "                    add_header Pragma \"no-cache\";\n" +
                "                    add_header Cache-Control \"no-store, no-cache, must-revalidate, post-check=0, pre-check=0\";\n" +
                "\n" +
                "                }\n" +
                "    }\n" +
                "    server {\n" +
                "            listen       80;\n" +
                "            server_name  lts.superseller.cn;\n" +
                "            charset utf-8;\n" +
                "            index /index.html; \n" +
                "            location / {\n" +
                "                    proxy_pass http://127.0.0.1:8382;\n" +
                "                    proxy_redirect              off;\n" +
                "                    proxy_set_header            Host $host;\n" +
                "                    proxy_set_header            X-Real-IP $remote_addr;\n" +
                "                    proxy_set_header            X-Forwarded-For $proxy_add_x_forwarded_for;\n" +
                "                    client_max_body_size 10m;\n" +
                "                    client_body_buffer_size 128k;\n" +
                "                    proxy_connect_timeout 90;\n" +
                "                    proxy_send_timeout 120;\n" +
                "                    proxy_read_timeout 120;\n" +
                "                    proxy_buffer_size 4k;\n" +
                "                    proxy_buffers 4 32k;\n" +
                "                    proxy_busy_buffers_size 64k;\n" +
                "                    proxy_temp_file_write_size 64k;\n" +
                "                    add_header Pragma \"no-cache\";\n" +
                "                    add_header Cache-Control \"no-store, no-cache, must-revalidate, post-check=0, pre-check=0\";\n" +
                "\n" +
                "                }\n" +
                "    }\n" +
                "\n" +
                "    \n").append(
                "    server {\n" +
                "        listen       80;\n" +
                "        server_name  overseas.superseller.cn cms.superseller.cn overseas.helloseller.cn;\n" +
                "\n" +
                "        #charset koi8-r;\n" +
                "\n" +
                "        #access_log  logs/host.access.log  main;\n" +
                "\n" +
                "        location / {\n" +
                "           content_by_lua '\n" +
                "                 local v = getVersion()\n" +
                "                 ngx.exec(\"@\" .. v) \n" +
                "            ';\n" +
                "        }\n");
                //版本配置开始
                int i=58000;
                Map<String,Integer> portMap = new HashMap<String, Integer>();
                for (Version version:versions){
                    portMap.put(version.getVersionId(),i++);
                }
                for (Version version:versions){
                    sb.append("location @"+version.getVersionId()+"{\n" +
                            "            proxy_pass http://127.0.0.1:"+ portMap.get(version.getVersionId()) +";\n" +
                            "            proxy_redirect              off;\n" +
                            "            proxy_set_header            Host $host;\n" +
                            "            proxy_set_header            X-Real-IP $remote_addr;\n" +
                            "            proxy_set_header            X-Forwarded-For $proxy_add_x_forwarded_for;\n" +
                            "            client_max_body_size 10m;\n" +
                            "            client_body_buffer_size 128k;\n" +
                            "            proxy_connect_timeout 90;\n" +
                            "            proxy_send_timeout 120;\n" +
                            "            proxy_read_timeout 120;\n" +
                            "            proxy_buffer_size 4k;\n" +
                            "            proxy_buffers 4 32k;\n" +
                            "            proxy_busy_buffers_size 64k;\n" +
                            "            proxy_temp_file_write_size 64k;\n" +
                            "            add_header Pragma \"no-cache\";\n" +
                            "            add_header Cache-Control \"no-store, no-cache, must-revalidate, post-check=0, pre-check=0\";\n" +
                            "\n" +
                            "        }\n");
                }
                //server域 配置结束
                sb.append("}\n");




        sb.append("    server {\n" +
                "        listen       80;\n" +
                "        server_name  static.superseller.cn;\n" +
                "\n" +
                "        #charset koi8-r;\n" +
                "\n" +
                "        #access_log  logs/host.access.log  main;\n" +
                "\n" +
                "        location / {\n" +
                "           content_by_lua '\n" +
                "                 local v = getVersion()\n" +
                "                 ngx.exec(\"@\" .. v) \n" +
                "            ';\n" +
                "        }\n");
        //版本配置开始

        for (Version version:versions){
            FrontProject frontStaticProject = frontProjectDAO.getFrontProjectByKey(version.getFrontProjectsInfo().split(";")[1]);
            String frontStaticGitPath = frontStaticProject.getGitPath();
            frontStaticGitPath=frontStaticGitPath.substring(frontStaticGitPath.lastIndexOf("/"),frontStaticGitPath.lastIndexOf(".git"));
            sb.append("location @"+version.getVersionId()+"{\n" +
                   "root   "+SystemConstant.FRONT_PATH+"/"+version.getFrontProjectsInfo().split(";")[1]+frontStaticGitPath +";\n" +
                    "            index  index.html index.htm;"+
                    "        }\n");
        }
        //server域 配置结束
        sb.append("}\n");


 //############################ https 配置 #############################
        sb.append(
                "    server {\n" +
                        "        listen       443 ssl;\n" +
                        "        server_name  overseas.superseller.cn;\n" +
                        "        ssl on;\n" +
                        "        ssl_certificate /data/superseller.crt;\n" +
                        "        ssl_certificate_key /data/superseller.key;\n"+
                        "\n" +
                        "        #charset koi8-r;\n" +
                        "\n" +
                        "        #access_log  logs/host.access.log  main;\n" +
                        "\n" +
                        "        location / {\n" +
                        "           content_by_lua '\n" +
                        "                 local v = getVersion()\n" +
                        "                 ngx.exec(\"@\" .. v) \n" +
                        "            ';\n" +
                        "        }\n");
        //版本配置开始
        for (Version version:versions){
            sb.append("location @"+version.getVersionId()+"{\n" +
                    "            proxy_pass http://127.0.0.1:"+ portMap.get(version.getVersionId()) +";\n" +
                    "            proxy_redirect              off;\n" +
                    "            proxy_set_header            Host $host;\n" +
                    "            proxy_set_header            X-Real-IP $remote_addr;\n" +
                    "            proxy_set_header            X-Forwarded-For $proxy_add_x_forwarded_for;\n" +
                    "            client_max_body_size 10m;\n" +
                    "            client_body_buffer_size 128k;\n" +
                    "            proxy_connect_timeout 90;\n" +
                    "            proxy_send_timeout 120;\n" +
                    "            proxy_read_timeout 120;\n" +
                    "            proxy_buffer_size 4k;\n" +
                    "            proxy_buffers 4 32k;\n" +
                    "            proxy_busy_buffers_size 64k;\n" +
                    "            proxy_temp_file_write_size 64k;\n" +
                    "            add_header Pragma \"no-cache\";\n" +
                    "            add_header Cache-Control \"no-store, no-cache, must-revalidate, post-check=0, pre-check=0\";\n" +
                    "\n" +
                    "        }\n");
        }
        //server域 配置结束
        sb.append("}\n");




        sb.append("    server {\n" +
                "        listen       443 ssl;\n" +
                "        server_name  static.superseller.cn;\n" +
                "        ssl on;\n" +
                "        ssl_certificate /data/superseller.crt;\n" +
                "        ssl_certificate_key /data/superseller.key;\n"+
                "\n" +
                "        #charset koi8-r;\n" +
                "\n" +
                "        #access_log  logs/host.access.log  main;\n" +
                "\n" +
                "        location / {\n" +
                "           content_by_lua '\n" +
                "                 local v = getVersion()\n" +
                "                 ngx.exec(\"@\" .. v) \n" +
                "            ';\n" +
                "        }\n");
        //版本配置开始

        for (Version version:versions){
            FrontProject frontStaticProject = frontProjectDAO.getFrontProjectByKey(version.getFrontProjectsInfo().split(";")[1]);
            String frontStaticGitPath = frontStaticProject.getGitPath();
            frontStaticGitPath=frontStaticGitPath.substring(frontStaticGitPath.lastIndexOf("/"),frontStaticGitPath.lastIndexOf(".git"));
            sb.append("location @"+version.getVersionId()+"{\n" +
                    "root   "+SystemConstant.FRONT_PATH+"/"+version.getFrontProjectsInfo().split(";")[1]+frontStaticGitPath +";\n" +
                    "            index  index.html index.htm;"+
                    "        }\n");
        }
        //server域 配置结束
        sb.append("}\n");


        //############################ https 配置结束 #############################



                //这里是各个版本配置

                for (Version version:versions){
                    sb.append("server {\n" +
                            "        listen "+portMap.get(version.getVersionId())+";\n");
                    //location 开始
                    FrontProject frontProject = frontProjectDAO.getFrontProjectByKey(version.getFrontProjectsInfo().split(";")[0]);
                    String frontGitPath = frontProject.getGitPath();
                    frontGitPath=frontGitPath.substring(frontGitPath.lastIndexOf("/"),frontGitPath.lastIndexOf(".git"));
                    sb.append("location ~ .*\\.(html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js|css|zip)$ {\n" +
                            "            root   "+SystemConstant.FRONT_PATH+"/"+version.getFrontProjectsInfo().split(";")[0]+frontGitPath+";\n" +
                            "            index  index.html index.htm;\n" +
                            "        }\n");
                    List<EndProjectInfo> endObjects = JSON.parseArray(version.getEndProjectsInfo(),EndProjectInfo.class);
                    for(EndProjectInfo end : endObjects){
                        sb.append("location "+end.getLocation()+" {\n" +
                                "            proxy_pass "+end.getProxyPath()+";\n" +
                                "            proxy_redirect              off;\n" +
                                "            proxy_set_header            Host $host;\n" +
                                "            proxy_set_header            X-Real-IP $remote_addr;\n" +
                                "            proxy_set_header            X-Forwarded-For $proxy_add_x_forwarded_for;\n" +
                                "            client_max_body_size 10m;\n" +
                                "            client_body_buffer_size 128k;\n" +
                                "            proxy_connect_timeout 90;\n" +
                                "            proxy_send_timeout 120;\n" +
                                "            proxy_read_timeout 120;\n" +
                                "            proxy_buffer_size 4k;\n" +
                                "            proxy_buffers 4 32k;\n" +
                                "            proxy_busy_buffers_size 64k;\n" +
                                "            proxy_temp_file_write_size 64k;\n" +
                                "            add_header Pragma \"no-cache\";\n" +
                                "            add_header Cache-Control \"no-store, no-cache, must-revalidate, post-check=0, pre-check=0\";\n" +
                                "\n" +
                                "        }\n");
                    }
                    //server 结束
                    sb.append("}\n");

                }
                //http域 配置结束
                sb.append("}\n");
        return sb.toString();
    }


}
